<input type="range" id="r"  min=0 max=255>
<input type="range" id="g" min=0 max=255>
<input type="range" id="b" min=0 max=255>
<div id="color" style="height: 100px;width: 100px;"></div>
<script>
  let callbacks = new Map()
  let reactivities = new Map()
  let usedReactivties = []
  let object = {
    r: 1,
    g: 1,
    b: 1
  }
  let po = reactive(object)
  const r = document.getElementById('r')
  const g = document.getElementById('g')
  const b = document.getElementById('b')
  const color = document.getElementById('color')
  effect(() => {
    // 单向绑定: 把 po 的 r 属性的值绑定给输入框的值 
    r.value = po.r
  })
  effect(() => { 
    g.value = po.g
  })
  effect(() => { 
    b.value = po.b
  })
  // 实现双向绑定
  r.addEventListener('input', event => po.r = event.target.value)
  g.addEventListener('input', event => po.g = event.target.value)
  b.addEventListener('input', event => po.b = event.target.value)

  effect(() => { 
   color.style.backgroundColor = `rgb(${po.r},${po.g},${po.b})`
  })

  function effect(callback) {
    // callbacks.push(callback)
    // 清空
    usedReactivties = []
    callback()
    console.log(usedReactivties);
    for (const reactivity of usedReactivties) {
      if (!callbacks.has(reactivity[0])) {
        callbacks.set(reactivity[0], new Map())
      }
      if (!callbacks.get(reactivity[0]).has(reactivity[1])) {
        callbacks.get(reactivity[0]).set(reactivity[1], [])
      }
      callbacks.get(reactivity[0]).get(reactivity[1]).push(callback)
    }
  }

  function reactive(obj) {
    if (reactivities.has(obj))
      return reactivities.get(obj)
    let proxy = new Proxy(obj, {
      set(obj, prop, val) {
        obj[prop] = val
        if (callbacks.has(obj))
          if (callbacks.get(obj).get(prop))
            for (const callback of callbacks.get(obj).get(prop)) {
              callback()
            }
        return obj[prop]
      },
      get(obj, prop) {
        // console.log(obj, prop)
        usedReactivties.push([obj, prop])
        if (typeof obj[prop] === "object") return reactive(obj[prop])
        return obj[prop]
      }
    })
    reactivities.set(obj, proxy)
    return proxy
  }
</script>
